home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
LANG
/
GOFER
/
scripts
/
Power
< prev
next >
Wrap
Text File
|
1994-01-03
|
4KB
|
130 lines
-- Power series
data Power a = Series [a]
instance Add a => Add (Power a) where
(Series (x:xs)) + (Series (y:ys)) = Series ((x+y):zs) where
Series zs = (Series xs) + (Series ys)
(Series (x:xs)) - (Series (y:ys)) = Series ((x-y):zs) where
Series zs = (Series xs) - (Series ys)
negate (Series (x:xs)) = Series ((-x):ys) where
Series ys = - (Series xs)
zero = Series zeros
instance LeftMul a b => LeftMul a (Power b) where
a * (Series bs) = Series [ a*b | b <- bs ]
instance Div a b => Div (Power a) b where
(Series as) / b = Series [ a/b | a <- as ]
instance (LeftMul a b, Add b) => LeftMul (Power a) (Power b) where
(Series as) * (Series bs) = Series cs where
cs = [ sum [ a*b | (a,b) <- zip (rtake n as) bs ] | n <- [1..] ]
instance (Mult a, Add a) => Mult (Power a) where
unit = const unit
const :: Add a => a -> Power a
const a = Series (a:zeros)
zeros :: Add a => [a]
zeros = zero:zeros
vX :: (Mult a, Add a) => Power a
vX = Series (zero:unit:zeros)
instance ( Div (Power a) a, LeftMul (Power a) (Power a),
Mult (Power a), Add (Power a),
Add a) => Div (Power a) (Power a) where
xs / ys = xs * (invert ys)
invert :: (Mult (Power a), Add (Power a),
Div (Power a) a) => (Power a) -> (Power a)
invert x = (Series (unit:ys))/x0
where Series (xs@(x0:_)) = x
ys = [ f(i) | i <- [1..] ]
f(n) = -(xs!!n)/x0 - sum [f(n-i)*(xs!!i)/x0 | i <- [1..n-1]]
{- The order of a nonzero power series is the least i for which the
i-th coefficient is nonzero. An infinite list of power series can be
summed if the orders form a sequence that tends to infinity. From
the computational point of view we have to be given some function
g :: Int -> Int such that g(n) is a lower bound for the order of the
n-th power series. -}
limSum :: Add a => (Int -> Int) -> [Power a] -> Power a
limSum g ps = Series [ f(n) | n <- [0..] ] where
f(n) = sum [ h n i | i <- [0..g(n)] ]
h n j = let Series zs = ps!!j in zs!!n
-- i > g(n) && m < n ==> h m i == zero
ptake :: Int -> (Power a) -> [a]
ptake n (Series xs) = take n xs
-- take and reverse
rtake :: Int -> [a] -> [a]
rtake n xs = f n xs [] where
f 0 _ as = as
f (n+1) (x:xs) as = f n xs (x:as)
zip :: [a] -> [b] -> [(a,b)]
zip [] _ = []
zip _ [] = []
zip (a:as) (b:bs) = (a,b):zip as bs
-- repeated differences
diffs :: (Div (Power a) Int,
Add (Power a),
Mult ((Power a,Int) -> (Power a,Int))) => [a] -> [a]
diffs xs = [ x | ( Series (x:_),_) <-
[(next^n) (Series xs,0) | n <- [0..]]]
where next (as,m) = let m' = m+1 in (((divX as) - as) / m',m')
divX :: (Power a) -> (Power a)
divX (Series as) = Series as' where _:as' = as
rtake0 :: Add a => Int -> [a] -> [a]
rtake0 n xs = (rtake n xs) ++ zeros
undiff :: (LeftMul Int (Power a),
Add (Power a)) => Int -> [a] -> [a]
undiff n xs = ys where
Series ys = z - n*(timesX z)
z = Series xs
timesX :: Add a => (Power a) -> (Power a)
timesX (Series as) = Series (zero:as)
-- rebuild coefficients
undiffs :: (LeftMul Int (Power a),
Add (Power a)) => Int -> Int -> [a] -> [a]
undiffs d 0 xs = rtake0 (d+1) xs
undiffs d (n+1) xs = (take (n+2) (undiff (d-n-1) (undiffs d n xs)))
++ rtake0 (d-n-1) xs
-- interpolation for integral polynomials
coeffs :: Int -> (Int -> Int) -> [Int]
coeffs d f = rtake (d+1) cs where
cs = undiffs d d (diffs [ f(n) | n <- [0..] ])
print :: (Text a, Add a, Mult a, Ord a) => Char -> a -> [a] -> String
print c x [] = show x
print c x xs | x == zero = pr c 1 xs
| otherwise = (show x)++(spr c 1 xs)
where
pr c _ [] = "0"
pr c n (x:xs) | x == zero = pr c (n+1) xs
| otherwise = (t x c n)++(spr c (n+1) xs)
spr c _ [] = ""
spr c n (x:xs) | x == zero = spr c (n+1) xs
| otherwise = (if x < zero then "" else "+")++
(t x c n)++(spr c (n+1) xs)
t x c n = (if x == unit then "" else
if x == -unit then "-" else show x)++[c]++
(if n == 1 then "" else "^"++show(n))
-- pretty print
display d f = print 'x' c0 cs where
c0:cs = coeffs d f